# uncomment to make verbose and run dovecotpw for comparison (must be in $PATH)
$debug=1; 

# Note dependency:
use Digest::Perl::MD5;

@ARGV == 1 or die "usage: crampass.pl <password>\n";

$pass = shift @ARGV;
defined $debug and print "using  /$pass/ as the user password\n";
$secret=$pass;
if (length $secret > 64) {
   defined $debug and print "hashing down long  password\n";
   $secret = Digest::Perl::MD5::md5($secret);
}   
defined $debug and print "using  /$secret/ as the shared secret\n";

$Ki = "$secret" ^ (chr(0x36) x 64);
$Ko = "$secret" ^ (chr(0x5c) x 64);

defined $debug and print "HMAC keys\ninner=/$Ki/\nouter=/$Ko/\n";

$innermd5 = Digest::Perl::MD5->new;
$innermd5->add($Ki);
# print "HEX2:",$innermd5->hexdigest(),"\n";
foreach (@{$innermd5->{_state}}) {
    print "$_\n";
}
$Ci = pack 'V4', @{$innermd5->{_state}};

print "$Ci\n";

$outermd5 = Digest::Perl::MD5->new;
$outermd5->add($Ko);
# print "HEX2:",$outermd5->hexdigest(),"\n";
$Co = pack 'V4', @{$outermd5->{_state}};

$innerhex=Digest::Perl::MD5::_encode_hex($Ci);
$outerhex=Digest::Perl::MD5::_encode_hex($Co);

defined $debug and print "hex: inner=/$innerhex/ outer=/$outerhex/\n";

print "{CRAM-MD5}$outerhex$innerhex\n";

# defined $debug and print "dovecotpw says:\n"; 
# defined $debug and system("dovecotpw -s CRAM-MD5 -p \"$pass\"");



